<?php

namespace system\core;

define("TAG_OPEN", "OPEN");
define("TAG_CLOSE", "CLOSE");
define("TAG_SINGLE", "SINGLE");
define("TAG_STATE_INSERT", "insert");
define("TAG_STATE_EXISTING", "existing");
define("TAG_STATE_REMOVE", "remove");

Abstract class abstractTag
{

	protected $_id;
	protected $_tagname;
	protected $_sourcestate;
	protected $_level;
	protected $_type;
	protected $_offset;
	protected $_length;
	protected $_text;
	protected $_attributes;
	protected $_message;
	protected $_parent;
	protected $_openTag;
	protected $_closeTag;
	protected $_children;
	protected $_siblings;
	protected $_blocktype;
	protected $_dependancy;
	protected $_styles;

	function stripDown()
	{
		unset($this->_sourcestate);
		unset($this->_offset);
		unset($this->_length);
		unset($this->_text);
		unset($this->_attributes);
		unset($this->_message);
		unset($this->_openTag);
		unset($this->_closeTag);
		unset($this->_blocktype);
		unset($this->_styles);
	}

	function setId($int)
	{
		$this->_id = $int;
	}

	function getId()
	{
		return $this->_id;
	}

	function setTagname($string)
	{
		$this->_tagname = $string;
	}

	function getTagname()
	{
		return $this->_tagname;
	}

	function setSourceState($string)
	{
		$this->_sourcestate = $string;
	}

	function getSourceState()
	{
		return $this->_sourcestate;
	}

	function setLevel($int)
	{
		$this->_level = $int;
	}

	function getLevel()
	{
		return $this->_level;
	}

	function setType($string)
	{
		$this->_type = $string;
	}

	function getType()
	{
		return $this->_type;
	}

	function setOffset($int)
	{
		$this->_offset = $int;
	}

	function getOffset()
	{
		return $this->_offset;
	}

	function setLength($int)
	{
		$this->_length = $int;
	}

	function getLength()
	{
		return $this->_length;
	}

	function setText($string)
	{
		$this->_text = $string;
	}

	function getText()
	{
		return $this->_text;
	}

	function getAttributes()
	{
		return $this->_attributes;
	}

	/*
	  function removeAttribute($id)
	  {
	  unset($this->_attributes[$id]);
	  }
	 */

	function setMessage($string)
	{
		$this->_message[] = $string;
	}

	function getMessage()
	{
		return $this->_message;
	}

	function addNotice($string)
	{
		$this->_message[] = $string;
	}

	function setParent($object)
	{
		$this->_parent = $object;
	}

	function getParent()
	{
		return $this->_parent;
	}

	function addSibling($object)
	{
		$this->setSiblings($object);
	}

	function setSiblings($object)
	{
		$this->_siblings[] = $object;
	}

	function getSiblings()
	{
		return $this->_siblings;
	}

	function hasSiblings()
	{
		if( $this->_siblings ) return true;
	}

	function setOpenTag($object)
	{
		$this->_openTag = $object;
	}

	function getOpenTag()
	{
		return $this->_openTag;
	}

	function setCloseTag($object)
	{
		$this->_closeTag = $object;
	}

	function getCloseTag()
	{
		return $this->_closeTag;
	}

	function setChildren($object)
	{
		$this->_children[] = $object;
	}

	function getChildren()
	{
		return $this->_children;
	}

	function addChild($object)
	{
		$this->setChildren($object);
	}

	function setDependancy($string)
	{
		$this->_dependancy = $string;
	}

	function getDependancy()
	{
		return $this->_dependancy;
	}

	function hasDependancy()
	{
		if( $this->_dependancy ) return true;
	}

	function setBlocktype($string)
	{
		$this->_blocktype = $string;
	}

	function getBlocktype()
	{
		return $this->_blocktype;
	}

	function setBlocklevel($string)
	{
		$this->setBlocktype($string);
	}

	function getBlocklevel()
	{
		return $this->getBlocktype();
	}

	/*
	  function setStyle($string)
	  {
	  $this->_style = $string;
	  }
	 *
	 */

	function getStyles()
	{
		return $this->_styles;
	}

	function startPos()
	{
		return $this->getOffset();
	}

	function endPos()
	{
		return $this->getOffset() + $this->getLength();
	}

	public function isOpenTag()
	{
		if( $this->getType() == TAG_OPEN ) return true;
	}

	public function isCloseTag()
	{
		if( $this->getType() == TAG_CLOSE ) return true;
	}

	public function isSingleTag()
	{
		if( $this->getType() == TAG_SINGLE ) return true;
	}

	public function hasCloseTag()
	{
		if( $this->_closeTag ) return true;
	}

	public function hasParent()
	{
		if( $this->_parent ) return true;
	}

	public function hasChildren()
	{
		if( $this->_children ) return true;
	}

	/*
	  public function hasAttributes()
	  {
	  if( $this->_attributes ) return true;
	  }

	  public function hasAttribute($key)
	  {
	  if( $this->getAttribute($key) ) return true;
	  }
	 */

	public function getTag()
	{
		$t.= "<";
		$t.= ($this->isCloseTag() ? "/" : "");
		$t.= $this->getTagname();
		$t.= ($this->isSingleTag() ? " /" : "");
		$t.= ">";
		return $t;
	}

	public function getAttribute($key, $searchOperator="=")
	{
		if( !$this->hasAttributes() ) return false;

		$needle = strtolower($key);
		foreach( $this->getAttributes() as $attrId => $attribute )
		{
			$haystack = $attribute->getKey();
			if( $this->evalStringByOperator($haystack, $searchOperator, $needle) )
			{
				return $attribute;
			}
		}
	}

	private function evalStringByOperator($haystack, $operator, $needle)
	{
		$hs = "Haystack[{$haystack}]";
		$nl = "Needle[{$needle}]";
		$searchOperatorIndex["="] = "{$nl} Matches Exactly {$hs}"; //Needle is exactly equal to haystack
		$searchOperatorIndex["|="] = "{$hs} Contains Prefix {$nl}"; //Needle is prefix of haystack
		$searchOperatorIndex["*="] = "{$hs} Contains Selector {$nl}"; //Needle is somewhere in the haystack
		$searchOperatorIndex["~="] = "{$hs} Contains Word Selector {$nl}"; //Needle is a full word somewhere in the haystack
		$searchOperatorIndex["$="] = "{$hs} Ends With Selector {$nl}"; //Needle matches the end of the haystack
		$searchOperatorIndex["!="] = "{$nl} Not Equal To {$hs}"; //Needle is not equal to haystack
		$searchOperatorIndex["^="] = "{$hs} Starts With Selector {$nl}"; //Needle matches the beginning of the haystack

		$translateOperator["="] = "Matches Exactly";
		$translateOperator["|="] = "Contains Prefix";
		$translateOperator["*="] = "Contains Selector";
		$translateOperator["~="] = "Contains Word Selector";
		$translateOperator["$="] = "Ends With Selector";
		$translateOperator["!="] = "Not Equal To";
		$translateOperator["^="] = "Starts With Selector";

		if( !isset($searchOperatorIndex[$operator]) ) throw new Exception("Unknown compare operator [{$operator}]");
//		echo "Debug: ".$searchOperatorIndex[$operator]."\n";

		$haystackLen = strlen($haystack);
		$needleLen = strlen($needle);
		if( $needle ) $matchAtPos = strpos($haystack, $needle);

		switch ($operator)
		{
			case "=":
				return ($haystack == $needle ? true : false);
				break;
			case "!=":
				return ($haystack != $needle ? true : false);
				break;
			case "*=":
				return ($matchAtPos !== false ? true : false);
				break;
			case "|=":
				$condition1 = ($matchAtPos === 0);
				$condition2 = (substr($haystack, $needleLen, 1) === "-");
				return (($condition1 && $condition2) === true);
				break;
			case "~=":
				$condition1 = ($needleLen > 0);
				$pieces = explode(" ", $haystack);
				$condition2 = in_array($needle, $pieces);
				return (($condition1 && $condition2) === true);
				break;
			case "^=":
				$condition1 = ($matchAtPos === 0);
				return ($condition1 === true ? true : false);
				break;
			case "$=":
				$condition1 = (($matchAtPos + $needleLen) == $haystackLen);
				return ($condition1 === true ? true : false);
				break;
			default:
				return false;
		}
	}

}

?>
